import {getCellId, initGraph, isNode, isNodeContent, loadStyle, setCurrentCellMark, setEdgeFlow} from "./utils";
import {InitProps, updateProps} from "../index";
import {flowStyle} from "@dreamof2080/flow-style";

const mx = require('mxgraph')({
  mxBasePath: 'mxgraph',
});

const {
  mxGraph,
  mxGraphModel,
  mxUtils,
  mxGeometry,
  mxCodec,
  mxPoint,
  mxConstants,
  mxEvent,
  mxCellTracker,
  mxOutline,
  mxCellOverlay,
  mxImage,
  mxEdgeStyle
} = mx;

// 通过xml加载流程图必须这样子使用
// @ts-ignore
window.mxGraphModel = mxGraphModel;
// @ts-ignore
window.mxGeometry = mxGeometry;
// @ts-ignore
window.mxPoint = mxPoint;
// @ts-ignore
window.mxUtils = mxUtils;
// @ts-ignore
window.mxCellTracker = mxCellTracker;
// @ts-ignore
window.mxOutline = mxOutline;
// @ts-ignore
window.mxCellOverlay = mxCellOverlay;
// @ts-ignore
window.mxImage = mxImage;
// @ts-ignore
window.mxEdgeStyle = mxEdgeStyle;

// 初始化
export const initFlowGraph = (option: InitProps) => {
  const {
    container,
    thumbnail,
    flowedEdgeColor = '#525050',
    style = flowStyle,
    shadowColor = '#050505',
    onClick
  } = option;
  // Disables the built-in context menu
  mxEvent.disableContextMenu(container);
  const graph = new mxGraph(container);
  // Highlights the vertices when the mouse enters
  new mxCellTracker(graph, '#00FF00');
  // 初始化
  initGraph(graph);
  graph.flowedEdgeColor = flowedEdgeColor;
  // cell阴影
  mxConstants.SHADOWCOLOR = shadowColor;
  // 加载样式
  // 流程图连接线的样式需要设置为mxEdgeStyle.ElbowConnector
  if (style.defaultEdgeStyle && style.defaultEdgeStyle?.edgeStyle == 'elbowConnector') {
    style.defaultEdgeStyle = {
      ...style.defaultEdgeStyle,
      'edgeStyle': mxEdgeStyle.ElbowConnector
    }
  }
  // @ts-ignore
  loadStyle(graph, style);
  // 缩略图
  if (thumbnail) {
    new mxOutline(graph, thumbnail)
  }

  // 鼠标点击事件
  if (onClick) {
    graph.addListener(mxEvent.CLICK, (sender: any, evt: any) => {
      const cell = evt.getProperty('cell');
      const event = evt.getProperty('event');
      if (cell && isNode(cell)) {
        const id = getCellId(cell);
        onClick(id, event.layerX, event.layerY)
      } else {
        onClick('', undefined, undefined);
      }
    })
  }
  return graph;
}

// 渲染流程图数据
export const renderFlowGraph = (props: updateProps) => {
  const {graph, data, currentIds, flowedEdgeIds} = props;
  if (flowedEdgeIds && flowedEdgeIds.length > 0) {
    // 拖动后重新渲染流水线效果
    graph.getView().addListener(mxEvent.TRANSLATE, () => {
      flowedEdgeIds.forEach((id: string) => {
        const cell = graph.getModel().getCell(id);
        if (cell && cell.isEdge()) {
          setEdgeFlow(graph, cell, graph.flowedEdgeColor || '#525050');
        }
      })
    });
  }
  if (data) {
    graph.getModel().beginUpdate();
    try {
      // 加载xml
      const xmlDocument = mxUtils.parseXml(data);
      const decoder = new mxCodec(xmlDocument);
      decoder.decode(xmlDocument.documentElement, graph.getModel());
      // 隐藏节点
      const nodes = xmlDocument.documentElement.getElementsByTagName(
        'mxCell',
      );
      for (let i = 0; i < nodes.length; i++) {
        const node = nodes.item(i);
        const cell = graph.getModel().getCell(node.getAttribute('id'));
        if (
          cell &&
          cell.isVertex() &&
          cell.getStyle().indexOf('visible=false') > -1
        ) {
          cell.setVisible(false);
          if (cell.edges && cell.edges.length > 0) {
            cell.edges.forEach((edge: any) => {
              edge.setVisible(false);
            });
          }
        }
      }
      // 当前节点标识
      if (currentIds && currentIds.length > 0) {
        currentIds.forEach((id: string) => {
          const cell = graph.getModel().getCell(id);
          if (cell) {
            setCurrentCellMark(graph, mxCellOverlay, mxImage, mxPoint, cell);
          }
        })
      }
    } finally {
      graph.getModel().endUpdate();
      // 已流转的连接线标识
      if (flowedEdgeIds && flowedEdgeIds.length > 0) {
        flowedEdgeIds.forEach((id: string) => {
          const cell = graph.getModel().getCell(id);
          if (cell && cell.isEdge()) {
            setEdgeFlow(graph, cell, graph.flowedEdgeColor || '#525050');
          }
        })
      }

    }
  }
}

export {getCellId, initGraph, isNode, isNodeContent, loadStyle, setCurrentCellMark, setEdgeFlow};
